#include <linux/init.h>       //初始化的头文件
#include <linux/module.h>     //最基本的文件，支持动态添加和卸载模块
#include <linux/fs.h>         //注册设备节点的文件结构体
#include <linux/miscdevice.h> //注册杂项设备头文件

static int chrdev_open(struct inode *inode, struct file *file)
{
    printk("This is chrdev_open \n");
    return 0;
}

static ssize_t chrdev_read(struct file *file, char __user *buf, size_t size, loff_t *off)
{
    printk("This is chrdev_read \n");
    return 0;
}

static ssize_t chrdev_write(struct file *file, const char __user *buf, size_t size, loff_t *off)
{
    printk("This is chrdev_write \n");
    return 0;
}
static int chrdev_release(struct inode *inode, struct file *file)
{
    return 0;
}

static struct file_operations misc_fops = {
    .owner = THIS_MODULE,      // 将owner字段指向本模块，可以避免在模块的操作正在被使用时卸载该模块
    .open = chrdev_open,       // 将open字段指向chrdev_open(...)函数
    .read = chrdev_read,       // 将open字段指向chrdev_read(...)函数
    .write = chrdev_write,     // 将open字段指向chrdev_write(...)函数
    .release = chrdev_release, // 将open字段指向chrdev_release(...)函数
}; // 定义file_operations结构体类型的变量misc_fops

struct miscdevice misc_dev = {
    // 杂项设备结构体
    .minor = MISC_DYNAMIC_MINOR, // 动态申请的次设备号
    .name = "hello_misc",        // 杂项设备名字是hello_misc
    .fops = &misc_fops,          // 文件操作集
};

static int __init misc_init(void) // 驱动入口函数
{
    int ret; // 定义int类型的变量ret，用来判断函数返回值

    ret = misc_register(&misc_dev); // 在初始化函数中注册杂项设备

    if (ret < 0)
    {
        printk("cdev_add is error\n");
    }

    printk("misc registe is succeed \n"); // 打印注册杂项设备成功

    return 0;
}
static void __exit misc_exit(void) // 驱动出口函数
{
    misc_deregister(&misc_dev); // 在卸载函数中注销杂项设备
    printk(" misc goodbye! \n");
    printk("module  exit \n");
}

module_init(misc_init);           // 注册入口函数
module_exit(misc_exit);           // 注册出口函数
MODULE_LICENSE("GPL v2");         // 同意GPL开源协议
MODULE_AUTHOR("wang fang chen "); // 作者信息
